<template>
  <base-table
    :url="url"
    :table-field-list="tableFieldList"
    :submit-form="submitForm"
    submit-form-title="角色信息"
    :fixed-func-btn="fixedFuncBtn"
    @set-form-init-value="setFormInitValue"
    @submit-valid="submitValid"
  >
    <template #submitForm>
      <el-form :model="submitForm" :label-width="100" ref="submitFormRef">
        <el-form-item label="角色名称：" prop="name">
          <el-input v-model="submitForm.name"></el-input>
        </el-form-item>
        <el-form-item label="角色描述：" prop="introduction">
          <el-input v-model="submitForm.introduction"></el-input>
        </el-form-item>
      </el-form>
    </template>
  </base-table>
  <el-dialog
    title="访问权限"
    v-model="menuAuthorityVisible"
    :close-on-click-modal="false"
  >
    <el-tree
      ref="menuTreeRef"
      :data="menuTree"
      :props="menuTreeProps"
      node-key="id"
      show-checkbox
      @check="changeSelectedMenuIds"
      highlight-current
      check-strictly
    ></el-tree>
    <template #footer>
      <el-button style="float: left" type="primary" @click="submitMenu()"
        >确认</el-button
      >
      <el-button @click="changeMenuAuthorityVisible()">关闭</el-button>
    </template>
  </el-dialog>
  <el-dialog
    title="操作权限"
    v-model="operationAuthorityVisible"
    :close-on-click-modal="false"
  >
    <template #footer>
      <el-button style="float: left" type="primary">确认</el-button>
      <el-button @click="changeOperationAuthorityVisible">关闭</el-button>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref } from "vue";

import BaseTable from "@/components/table/basic/BaseTable.vue";

import api from "@/utils";
import { FixedFuncBtn, TableField, TableUrl } from "@/models/TableSetting";

import { Role } from "@/models/dataPeople/Role";
import { Menu } from "@/models/Menu";
import { AxiosResponse } from "axios";
import { RoleMenuRelation } from "@/models/system/RoleMenuRelation";
import { ElMessage } from "element-plus";

const url = {
  refreshUrl: "/basic-request/Role",
  modifyingSingleUrl: "/basic-request/Role",
  deleteUrl: "/basic-request/Role/batchDelete",
} as TableUrl;

const tableFieldList = [
  {
    filedName: "name",
    label: "角色名称",
    width: 200,
  },
  {
    filedName: "introduction",
    label: "角色描述",
    minWidth: 220,
  },
  {
    filedName: "createUser",
    label: "创建人",
    width: 220,
  },
  {
    filedName: "createGmt",
    label: "创建时间",
    width: 220,
  },
] as Array<TableField>;

const menuAuthorityVisible = ref(false);
const changeMenuAuthorityVisible = () => {
  menuAuthorityVisible.value = !menuAuthorityVisible.value;
};
const operationAuthorityVisible = ref(false);
const changeOperationAuthorityVisible = () => {
  operationAuthorityVisible.value = !operationAuthorityVisible.value;
};

const menuTree = ref([] as Menu[]);

const currentRoleId = ref();

// 申明表单
const submitFormRef = ref();
const submitForm = ref({} as Role);
const fixedFuncBtn = ref({
  width: 240,
  button: [
    {
      name: "访问权限",
      icon: "compass",
      type: "text",
      method: (row: Role) => {
        currentRoleId.value = row.id;
        changeMenuAuthorityVisible();
        api.http
          .get("/system/selectMenuIdByRoleId/" + row.id)
          .then((res: AxiosResponse) => {
            menuTreeRef.value.setCheckedKeys(res.data);
          });
      },
    },
    {
      name: "操作权限",
      icon: "set-up",
      type: "text",
      method: (row: Role) => {
        console.log(row);
        changeOperationAuthorityVisible();
      },
    },
  ],
} as FixedFuncBtn);

const setFormInitValue = (formType: string, row: Role) => {
  if (undefined !== submitFormRef.value) {
    submitFormRef.value.clearValidate();
  }
  switch (formType) {
    case "insert":
      submitForm.value = {
        name: "",
        introduction: "",
        createUser: "root",
        createGmt: new Date(),
      } as Role;
      break;
    case "update":
      submitForm.value = row;
      break;
  }
};

/**
 * 提交数据前的校验
 * @param callback 回调函数,将校验结果返还到Table组件中.
 */
const submitValid = (callback: (value: boolean) => void) => {
  submitFormRef.value
    .validate()
    .then(() => {
      callback(true);
    })
    .catch(() => {
      callback(false);
    });
};

const menuTreeRef = ref();

const menuTreeProps = {
  children: "children",
  label: "title",
};

const selectMenuTree = () => {
  api.http.get("/system/selectAllMenuTree").then((res: AxiosResponse) => {
    menuTree.value = res.data;
  });
};
selectMenuTree();

const selectedParent = (checkedNodes: Menu) => {
  let currentNode = menuTreeRef.value.getNode(checkedNodes);
  if (currentNode.parent.key !== undefined) {
    menuTreeRef.value.setChecked(currentNode.parent, true);
    selectedParent(currentNode.parent);
  }
};

const uniteChildSame = (treeList: Menu, isSelected: boolean) => {
  menuTreeRef.value.setChecked(treeList.id, isSelected);
  if (treeList.children) {
    for (let i = 0; i < treeList.children.length; i++) {
      uniteChildSame(treeList.children[i], isSelected);
    }
  }
};

/**
 * 设置当前节点的父节点的勾选状态.
 */
const setParentNodeValue = (checkedNodes: Menu) => {
  const currentNode = menuTreeRef.value.getNode(checkedNodes);
  let unchecked = true;
  currentNode.parent.childNodes.forEach((item: Record<string, unknown>) => {
    if (item.checked) {
      unchecked = false;
    }
  });
  if (unchecked) {
    menuTreeRef.value.setChecked(currentNode.parent, false);
  }
};

/**
 * 勾选项发生改变时, 重新设置选择的值
 * @param checkedNodes 当改变的勾选项
 * @param treeStatus 树结构当前的状态
 */
const changeSelectedMenuIds = (
  checkedNodes: Menu,
  treeStatus: Record<string, Array<unknown>>
) => {
  // 用于：父子节点严格互不关联时，父节点勾选变化时通知子节点同步变化，实现单向关联。
  let selected = treeStatus.checkedKeys.indexOf(checkedNodes.id);
  if (selected !== -1) {
    // 子节点只要被选中父节点就被选中
    selectedParent(checkedNodes);
    // 统一处理子节点为相同的勾选状态
    uniteChildSame(checkedNodes, true);
  } else {
    setParentNodeValue(checkedNodes);
    // 父节点未选中时 使子节点全部未选中
    if (checkedNodes.children?.length !== 0) {
      uniteChildSame(checkedNodes, false);
    }
  }
};

const submitMenu = () => {
  console.log(menuTreeRef.value.getCheckedKeys());
  const roleMenuRelation = [] as RoleMenuRelation[];
  menuTreeRef.value.getCheckedKeys().forEach((item: number) => {
    roleMenuRelation.push({
      roleId: currentRoleId.value,
      menuId: item,
      createUser: sessionStorage.getItem("token") as string,
      createGmt: new Date(),
    });
  });
  api.http
    .postJson("/system/setRoleMenuRelation", roleMenuRelation)
    .then(() => {
      ElMessage.success("设置成功!");
    })
    .catch(() => {
      ElMessage.error("设置失败!");
    });
};
</script>

<style scoped></style>
